﻿using System;
using System.Diagnostics;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace RxVSMSampleP2.CompositeEvent
{
    /// <summary>
    ///     Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DragNDrop(lblDragMe).Subscribe(dropPos =>
            {
                Canvas.SetLeft(lblDragMe, dropPos.X);
                Canvas.SetTop(lblDragMe, dropPos.Y);
            });
        }

        private IObservable<Point> DragNDrop(Control elem)
        {
            var mouseDownPos = from evt in Observable.FromEvent<MouseButtonEventArgs>(
                ev => elem.MouseDown += (s, e) => ev(e),
                ev => elem.MouseDown -= (s, e) => ev(e))
                               select LogPosition("mouseDown", evt.GetPosition(elem));

            var mouseMovePos = from evt in Observable.FromEvent<MouseEventArgs>(
                ev => MouseMove += (s, e) => ev(e),
                ev => MouseMove -= (s, e) => ev(e))
                               select LogPosition("mouseMove", evt.GetPosition(this));

            var mouseUp = Observable.FromEvent<MouseButtonEventArgs>(
                ev => elem.MouseUp += (s, e) => ev(e),
                ev => elem.MouseUp -= (s, e) => ev(e)).
                   Select(evt => LogPosition("mouseUp", evt.GetPosition(this)));

            var dropPos = from elemOffset in mouseDownPos
                          from pos in mouseMovePos.TakeUntil(mouseUp)
                          select new Point
                          {
                              X = pos.X - elemOffset.X,
                              Y = pos.Y - elemOffset.Y
                          };

            return dropPos;
        }

        private Point LogPosition(string source, Point point)
        {
            Debug.WriteLine("{0} fired x: {1} y: {2}", source, point.X, point.Y);
            return point;
        }
    }
}